package app

import (
	"encoding/json"
	"os/exec"

	"gitee.com/extrame/fb-runner/util"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

func Install(base, file string) error {
	//peer lifecycle chaincode install ~/anhui1.tar.gz
	for k, org := range util.Config.GetPeerOrganizations() {
		cmd := exec.Command("peer", "lifecycle", "chaincode", "install", file)
		util.UseOrg(cmd, base, org, true)
		logrus.Info(k, " run peer with env", cmd.Env)
		_, _, err := util.Run(cmd)
		if err != nil {
			return err
		}
		logrus.Info(k, "安装完成")
	}
	return nil
}

type OutputJson struct {
	InstalledChaincodes []*Chaincode `json:"installed_chaincodes"`
}

func (o *OutputJson) MarkHistoric() {
	var codesMap = make(map[string][]*Chaincode)
	for _, code := range o.InstalledChaincodes {
		var arr = codesMap[code.Label]
		if arr == nil {
			arr = []*Chaincode{code}
		} else if len(code.References) > 0 {
			arr = append([]*Chaincode{code}, arr...)
		} else {
			arr = append(arr, code)
		}
		codesMap[code.Label] = arr
	}
	for _, arr := range codesMap {
		var hasCommited = false
		for _, code := range arr {
			if len(code.References) > 0 {
				for channel, detail := range code.References {
					//TODO 咱不支持多个reference的情况（一个chaincode被安装在多个地方）
					code.Channel = channel
					code.Approved = true
					code.Commited = true
					code.VersionLabel = detail.Chaincodes[0].Version
					code.Version = uint64(len(arr))
					hasCommited = true
				}
			} else {
				code.Historic = hasCommited
			}
		}
	}
}

func CheckInstall(base string) (err error) {
	//peer lifecycle chaincode install ~/anhui1.tar.gz
	for _, org := range util.Config.GetPeerOrganizations() {
		cmd := exec.Command("peer", "lifecycle", "chaincode", "queryinstalled", "--output", "json")
		util.UseOrg(cmd, base, org, true)
		var stdout string
		stdout, _, err = util.Run(cmd, true)
		if err != nil {
			return err
		}
		var out OutputJson
		err = json.Unmarshal([]byte(stdout), &out)
		if err != nil {
			return errors.Wrap(err, "unmarshall message"+stdout)
		}
		out.MarkHistoric()
		newCode := CheckNewInstall(out.InstalledChaincodes)

		logrus.Info("完成安装确认：", newCode)
		return err
	}
	return nil
}
